﻿
namespace Aeon.Emulator.Video
{
    /// <summary>
    /// Emulates the VGA Graphics registers.
    /// </summary>
    internal sealed class Graphics : VideoComponent
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the Graphics class.
        /// </summary>
        /// <param name="heap">Heap used to allocate unmanaged memory.</param>
        public Graphics(NativeHeap heap)
        {
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets or sets the Set/Reset register.
        /// </summary>
        public byte SetReset { get; private set; }
        /// <summary>
        /// Gets or sets the Enable Set/Reset register.
        /// </summary>
        public byte EnableSetReset { get; private set; }
        /// <summary>
        /// Gets or sets the Color Compare register.
        /// </summary>
        public byte ColorCompare { get; private set; }
        /// <summary>
        /// Gets or sets the Data Rotate register.
        /// </summary>
        public byte DataRotate { get; private set; }
        /// <summary>
        /// Gets or sets the Read Map Select register.
        /// </summary>
        public byte ReadMapSelect { get; private set; }
        /// <summary>
        /// Gets or sets the Graphics Mode register.
        /// </summary>
        public byte GraphicsMode { get; set; }
        /// <summary>
        /// Gets or sets the Miscellaneous Graphics register.
        /// </summary>
        public byte MiscellaneousGraphics { get; set; }
        /// <summary>
        /// Gets or sets the Color Don't Care register.
        /// </summary>
        public byte ColorDontCare { get; private set; }
        /// <summary>
        /// Gets or sets the Bit Mask register.
        /// </summary>
        public byte BitMask { get; set; }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns the current value of a graphics register.
        /// </summary>
        /// <param name="address">Address of register to read.</param>
        /// <returns>Current value of the register.</returns>
        public byte ReadRegister(GraphicsRegister address)
        {
            switch(address)
            {
            case GraphicsRegister.SetReset:
                return SetReset;

            case GraphicsRegister.EnableSetReset:
                return EnableSetReset;

            case GraphicsRegister.ColorCompare:
                return ColorCompare;

            case GraphicsRegister.DataRotate:
                return DataRotate;

            case GraphicsRegister.ReadMapSelect:
                return ReadMapSelect;

            case GraphicsRegister.GraphicsMode:
                return GraphicsMode;

            case GraphicsRegister.MiscellaneousGraphics:
                return MiscellaneousGraphics;

            case GraphicsRegister.ColorDontCare:
                return ColorDontCare;

            case GraphicsRegister.BitMask:
                return BitMask;

            default:
                return 0;
            }
        }
        /// <summary>
        /// Writes to a graphics register.
        /// </summary>
        /// <param name="address">Address of register to write.</param>
        /// <param name="value">Value to write to register.</param>
        public void WriteRegister(GraphicsRegister address, byte value)
        {
            switch(address)
            {
            case GraphicsRegister.SetReset:
                SetReset = value;
                ExpandRegister(value, ExpandedSetReset);
                break;

            case GraphicsRegister.EnableSetReset:
                EnableSetReset = value;
                ExpandRegister(value, ExpandedEnableSetReset);
                break;

            case GraphicsRegister.ColorCompare:
                ColorCompare = value;
                ExpandRegister(value, ExpandedColorCompare);
                break;

            case GraphicsRegister.DataRotate:
                DataRotate = value;
                break;

            case GraphicsRegister.ReadMapSelect:
                ReadMapSelect = value;
                break;

            case GraphicsRegister.GraphicsMode:
                GraphicsMode = value;
                break;

            case GraphicsRegister.MiscellaneousGraphics:
                MiscellaneousGraphics = value;
                break;

            case GraphicsRegister.ColorDontCare:
                ColorDontCare = value;
                ExpandRegister(value, ExpandedColorDontCare);
                break;

            case GraphicsRegister.BitMask:
                BitMask = value;
                break;

            default:
                break;
            }
        }
        #endregion

        #region Public Fields
        /// <summary>
        /// Color compare register expanded out to four bytes.
        /// </summary>
        public readonly byte[] ExpandedColorCompare = new byte[4];
        /// <summary>
        /// Color don't care register expanded out to four bytes.
        /// </summary>
        public readonly byte[] ExpandedColorDontCare = new byte[4];
        /// <summary>
        /// Set/Reset register expanded out to four bytes.
        /// </summary>
        public readonly byte[] ExpandedSetReset = new byte[4];
        /// <summary>
        /// Enable Set/Reset register expanded out to four booleans.
        /// </summary>
        public readonly bool[] ExpandedEnableSetReset = new bool[4];
        #endregion
    }
}
